package ca.tatham.triplipse.filter;

import java.util.EnumMap;
import java.util.Map;

import org.eclipse.jface.dialogs.TrayDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class RdfStatementFilterDialog extends TrayDialog {

	private FilterChoice m_filterAny;
	private FilterChoice m_filterSubject;
	private FilterChoice m_filterPredicate;
	private FilterChoice m_filterObject;

	private final IRdfFilterListener m_filterListener;
	private IRdfStatementFilter m_filter;

	public RdfStatementFilterDialog(Shell shell,
			IRdfFilterListener rdfFilterListener,
			IRdfStatementFilter initialFilter) {
		super(shell);
		setShellStyle(getShellStyle() | SWT.RESIZE);
		m_filterListener = rdfFilterListener;
		m_filter = initialFilter;
	}

	protected void configureShell(Shell newShell) {
		super.configureShell(newShell);
		newShell.setText("RdfStatement Filters");
	}

	private IRdfFilterListener getFilterListener() {
		return m_filterListener;
	}

	@Override
	protected Control createDialogArea(Composite parent) {
		Composite composite = (Composite) super.createDialogArea(parent);
		// Composite myComposite = new Composite(composite, SWT.NULL);
		Map<RdfStatementFilterPart.FilterField, RdfStatementFilterPart> filters = createFilterMap();
		composite.setLayout(new GridLayout(3, false));

		m_filterAny = new FilterChoice(composite, "Any Field", filters
				.get(RdfStatementFilterPart.FilterField.ANY));
		m_filterSubject = new FilterChoice(composite, "Subject", filters
				.get(RdfStatementFilterPart.FilterField.SUBJECT));
		m_filterPredicate = new FilterChoice(composite, "Predicate", filters
				.get(RdfStatementFilterPart.FilterField.PREDICATE));
		m_filterObject = new FilterChoice(composite, "Object", filters
				.get(RdfStatementFilterPart.FilterField.OBJECT));

		return composite;
	}

	private Map<RdfStatementFilterPart.FilterField, RdfStatementFilterPart> createFilterMap() {
		Map<RdfStatementFilterPart.FilterField, RdfStatementFilterPart> filters = new EnumMap<RdfStatementFilterPart.FilterField, RdfStatementFilterPart>(
				RdfStatementFilterPart.FilterField.class);
		if (m_filter != null && m_filter instanceof RdfStatementFilterComposite) {
			for (IRdfStatementFilter part : ((RdfStatementFilterComposite) m_filter)
					.getFilters()) {
				RdfStatementFilterPart rdfStatementFilterPart = ((RdfStatementFilterPart) part);
				filters.put(rdfStatementFilterPart.getField(),
						rdfStatementFilterPart);
			}
		}
		return filters;
	}

	@Override
	protected void okPressed() {
		final IRdfStatementFilter filter = buildFilter();
		super.okPressed();
		getFilterListener().setFilter(filter);
		clearFilters();
	}

	private void clearFilters() {
		m_filterAny.clear();
		m_filterSubject.clear();
		m_filterPredicate.clear();
		m_filterObject.clear();
	}

	protected IRdfStatementFilter buildFilter() {
		if (m_filterAny.isEmpty() && m_filterSubject.isEmpty()
				&& m_filterPredicate.isEmpty() && m_filterObject.isEmpty()) {
			return null;
		}
		RdfStatementFilterComposite filter = new RdfStatementFilterComposite();
		filter.addFilter(m_filterAny
				.getFilter(RdfStatementFilterPart.FilterField.ANY));
		filter.addFilter(m_filterSubject
				.getFilter(RdfStatementFilterPart.FilterField.SUBJECT));
		filter.addFilter(m_filterPredicate
				.getFilter(RdfStatementFilterPart.FilterField.PREDICATE));
		filter.addFilter(m_filterObject
				.getFilter(RdfStatementFilterPart.FilterField.OBJECT));
		return filter;
	}

}

class FilterChoice {
	private Text m_textFilter;
	private Button m_include;
	private Button m_exclude;

	public FilterChoice(Composite parent, String name,
			RdfStatementFilterPart filter) {
		Label label = new Label(parent, SWT.BOLD);
		label.setText(name);
		label.setEnabled(true);

		m_textFilter = new Text(parent, SWT.LEAD | SWT.SINGLE | SWT.BORDER);
		m_textFilter.setEnabled(true);
		if (filter != null) {
			m_textFilter.setText(filter.getFilter());
		}

		Composite buttons = new Composite(parent, SWT.NULL);
		buttons.setLayout(new RowLayout(SWT.HORIZONTAL));
		m_include = new Button(buttons, SWT.RADIO);
		m_include.setText("Include");
		m_exclude = new Button(buttons, SWT.RADIO);
		m_exclude.setText("Exclude");
		if (filter == null
				|| filter.getType() == RdfStatementFilterPart.FilterType.INCLUDE) {
			m_include.setSelection(true);
		} else {
			m_exclude.setSelection(true);
		}
	}

	public void clear() {
		m_textFilter.setText("");
	}

	boolean isEmpty() {
		return m_textFilter.getText().trim().length() < 1;
	}

	IRdfStatementFilter getFilter(RdfStatementFilterPart.FilterField field) {
		if (isEmpty()) {
			return null;
		}
		return new RdfStatementFilterPart(m_textFilter.getText(),
				getFilterType(), field);
	}

	RdfStatementFilterPart.FilterType getFilterType() {
		return m_include.isEnabled() ? RdfStatementFilterPart.FilterType.INCLUDE
				: RdfStatementFilterPart.FilterType.EXCLUDE;
	}

}
